/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package javax.print;

import java.util.Locale;

import javax.print.attribute.Attribute;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.event.PrintServiceAttributeListener;


/**
 * Interface PrintService is the factory for a DocPrintJob. A PrintService
 * describes the capabilities of a Printer and can be queried regarding
 * a printer's supported attributes.
 * <P>
 * Example:
 * <PRE>{@code
 * DocFlavor flavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
 * PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
 * aset.add(MediaSizeName.ISO_A4);
 * PrintService[] pservices =
 * PrintServiceLookup.lookupPrintServices(flavor, aset);
 * if (pservices.length > 0) {
 * DocPrintJob pj = pservices[0].createPrintJob();
 * try {
 * FileInputStream fis = new FileInputStream("test.ps");
 * Doc doc = new SimpleDoc(fis, flavor, null);
 * pj.print(doc, aset);
 * } catch (FileNotFoundException fe) {
 * } catch (PrintException e) {
 * }
 * }
 * }</PRE>
 */
public interface PrintService {

  /**
   * Returns a String name for this print service which may be used
   * by applications to request a particular print service.
   * In a suitable context, such as a name service, this name must be
   * unique.
   * In some environments this unique name may be the same as the user
   * friendly printer name defined as the
   * {@link javax.print.attribute.standard.PrinterName PrinterName}
   * attribute.
   *
   * @return name of the service.
   */
  public String getName();

  /**
   * Creates and returns a PrintJob capable of handling data from
   * any of the supported document flavors.
   *
   * @return a DocPrintJob object
   */
  public DocPrintJob createPrintJob();

  /**
   * Registers a listener for events on this PrintService.
   *
   * @param listener a PrintServiceAttributeListener, which monitors the status of a print service
   * @see #removePrintServiceAttributeListener
   */
  public void addPrintServiceAttributeListener(
      PrintServiceAttributeListener listener);

  /**
   * Removes the print-service listener from this print service.
   * This means the listener is no longer interested in
   * <code>PrintService</code> events.
   *
   * @param listener a PrintServiceAttributeListener object
   * @see #addPrintServiceAttributeListener
   */
  public void removePrintServiceAttributeListener(
      PrintServiceAttributeListener listener);

  /**
   * Obtains this print service's set of printer description attributes
   * giving this Print Service's status. The returned attribute set object
   * is unmodifiable. The returned attribute set object is a "snapshot" of
   * this Print Service's attribute set at the time of the
   * <CODE>getAttributes()</CODE> method call: that is, the returned
   * attribute set's contents will <I>not</I> be updated if this print
   * service's attribute set's contents change in the future. To detect
   * changes in attribute values, call <CODE>getAttributes()</CODE> again
   * and compare the new attribute set to the previous attribute set;
   * alternatively, register a listener for print service events.
   *
   * @return Unmodifiable snapshot of this Print Service's attribute set. May be empty, but not
   * null.
   */
  public PrintServiceAttributeSet getAttributes();

  /**
   * Gets the value of the single specified service attribute.
   * This may be useful to clients which only need the value of one
   * attribute and want to minimize overhead.
   *
   * @param category the category of a PrintServiceAttribute supported by this service - may not be
   * null.
   * @return the value of the supported attribute or null if the attribute is not supported by this
   * service.
   * @throws NullPointerException if the category is null.
   * @throws IllegalArgumentException (unchecked exception) if <CODE>category</CODE> is not a
   * <code>Class</code> that implements interface {@link javax.print.attribute.PrintServiceAttribute
   * PrintServiceAttribute}.
   */
  public <T extends PrintServiceAttribute>
  T getAttribute(Class<T> category);

  /**
   * Determines the print data formats a client can specify when setting
   * up a job for this <code>PrintService</code>. A print data format is
   * designated by a "doc
   * flavor" (class {@link javax.print.DocFlavor DocFlavor})
   * consisting of a MIME type plus a print data representation class.
   * <P>
   * Note that some doc flavors may not be supported in combination
   * with all attributes. Use <code>getUnsupportedAttributes(..)</code>
   * to validate specific combinations.
   *
   * @return Array of supported doc flavors, should have at least one element.
   */
  public DocFlavor[] getSupportedDocFlavors();

  /**
   * Determines if this print service supports a specific
   * <code>DocFlavor</code>.  This is a convenience method to determine
   * if the <code>DocFlavor</code> would be a member of the result of
   * <code>getSupportedDocFlavors()</code>.
   * <p>
   * Note that some doc flavors may not be supported in combination
   * with all attributes. Use <code>getUnsupportedAttributes(..)</code>
   * to validate specific combinations.
   *
   * @param flavor the <code>DocFlavor</code>to query for support.
   * @return <code>true</code> if this print service supports the specified <code>DocFlavor</code>;
   * <code>false</code> otherwise.
   * @throws NullPointerException (unchecked exception) Thrown if <CODE>flavor</CODE> is null.
   */
  public boolean isDocFlavorSupported(DocFlavor flavor);


  /**
   * Determines the printing attribute categories a client can specify
   * when setting up a job for this print service.
   * A printing attribute category is
   * designated by a <code>Class</code> that implements interface
   * {@link javax.print.attribute.Attribute Attribute}. This method returns
   * just the attribute <I>categories</I> that are supported; it does not
   * return the particular attribute <I>values</I> that are supported.
   * <P>
   * This method returns all the printing attribute
   * categories this print service supports for any possible job.
   * Some categories may not be supported in a particular context (ie
   * for a particular <code>DocFlavor</code>).
   * Use one of the methods that include a <code>DocFlavor</code> to
   * validate the request before submitting it, such as
   * <code>getSupportedAttributeValues(..)</code>.
   *
   * @return Array of printing attribute categories that the client can specify as a doc-level or
   * job-level attribute in a Print Request. Each element in the array is a {@link java.lang.Class
   * Class} that implements interface {@link javax.print.attribute.Attribute Attribute}. The array
   * is empty if no categories are supported.
   */
  public Class<?>[] getSupportedAttributeCategories();

  /**
   * Determines whether a client can specify the given printing
   * attribute category when setting up a job for this print service. A
   * printing attribute category is designated by a <code>Class</code>
   * that implements interface {@link javax.print.attribute.Attribute
   * Attribute}. This method tells whether the attribute <I>category</I> is
   * supported; it does not tell whether a particular attribute <I>value</I>
   * is supported.
   * <p>
   * Some categories may not be supported in a particular context (ie
   * for a particular <code>DocFlavor</code>).
   * Use one of the methods which include a <code>DocFlavor</code> to
   * validate the request before submitting it, such as
   * <code>getSupportedAttributeValues(..)</code>.
   * <P>
   * This is a convenience method to determine if the category
   * would be a member of the result of
   * <code>getSupportedAttributeCategories()</code>.
   *
   * @param category Printing attribute category to test. It must be a <code>Class</code> that
   * implements interface {@link javax.print.attribute.Attribute Attribute}.
   * @return <code>true</code> if this print service supports specifying a doc-level or job-level
   * attribute in <CODE>category</CODE> in a Print Request; <code>false</code> if it doesn't.
   * @throws NullPointerException (unchecked exception) Thrown if <CODE>category</CODE> is null.
   * @throws IllegalArgumentException (unchecked exception) Thrown if <CODE>category</CODE> is not a
   * <code>Class</code> that implements interface {@link javax.print.attribute.Attribute
   * Attribute}.
   */
  public boolean
  isAttributeCategorySupported(Class<? extends Attribute> category);

  /**
   * Determines this print service's default printing attribute value in
   * the given category. A printing attribute value is an instance of
   * a class that implements interface
   * {@link javax.print.attribute.Attribute Attribute}. If a client sets
   * up a print job and does not specify any attribute value in the
   * given category, this Print Service will use the
   * default attribute value instead.
   * <p>
   * Some attributes may not be supported in a particular context (ie
   * for a particular <code>DocFlavor</code>).
   * Use one of the methods that include a <code>DocFlavor</code> to
   * validate the request before submitting it, such as
   * <code>getSupportedAttributeValues(..)</code>.
   * <P>
   * Not all attributes have a default value. For example the
   * service will not have a defaultvalue for <code>RequestingUser</code>
   * i.e. a null return for a supported category means there is no
   * service default value for that category. Use the
   * <code>isAttributeCategorySupported(Class)</code> method to
   * distinguish these cases.
   *
   * @param category Printing attribute category for which the default attribute value is requested.
   * It must be a {@link java.lang.Class Class} that implements interface {@link
   * javax.print.attribute.Attribute Attribute}.
   * @return Default attribute value for <CODE>category</CODE>, or null if this Print Service does
   * not support specifying a doc-level or job-level attribute in <CODE>category</CODE> in a Print
   * Request, or the service does not have a default value for this attribute.
   * @throws NullPointerException (unchecked exception) Thrown if <CODE>category</CODE> is null.
   * @throws IllegalArgumentException (unchecked exception) Thrown if <CODE>category</CODE> is not a
   * {@link java.lang.Class Class} that implements interface {@link javax.print.attribute.Attribute
   * Attribute}.
   */
  public Object
  getDefaultAttributeValue(Class<? extends Attribute> category);

  /**
   * Determines the printing attribute values a client can specify in
   * the given category when setting up a job for this print service. A
   * printing
   * attribute value is an instance of a class that implements interface
   * {@link javax.print.attribute.Attribute Attribute}.
   * <P>
   * If <CODE>flavor</CODE> is null and <CODE>attributes</CODE> is null
   * or is an empty set, this method returns all the printing attribute
   * values this Print Service supports for any possible job. If
   * <CODE>flavor</CODE> is not null or <CODE>attributes</CODE> is not
   * an empty set, this method returns just the printing attribute values
   * that are compatible with the given doc flavor and/or set of attributes.
   * That is, a null return value may indicate that specifying this attribute
   * is incompatible with the specified DocFlavor.
   * Also if DocFlavor is not null it must be a flavor supported by this
   * PrintService, else IllegalArgumentException will be thrown.
   * <P>
   * If the <code>attributes</code> parameter contains an Attribute whose
   * category is the same as the <code>category</code> parameter, the service
   * must ignore this attribute in the AttributeSet.
   * <p>
   * <code>DocAttribute</code>s which are to be specified on the
   * <code>Doc</code> must be included in this set to accurately
   * represent the context.
   * <p>
   * This method returns an Object because different printing attribute
   * categories indicate the supported attribute values in different ways.
   * The documentation for each printing attribute in package {@link
   * javax.print.attribute.standard javax.print.attribute.standard}
   * describes how each attribute indicates its supported values. Possible
   * ways of indicating support include:
   * <UL>
   * <LI>
   * Return a single instance of the attribute category to indicate that any
   * value is legal -- used, for example, by an attribute whose value is an
   * arbitrary text string. (The value of the returned attribute object is
   * irrelevant.)
   * <LI>
   * Return an array of one or more instances of the attribute category,
   * containing the legal values -- used, for example, by an attribute with
   * a list of enumerated values. The type of the array is an array of the
   * specified attribute category type as returned by its
   * <code>getCategory(Class)</code>.
   * <LI>
   * Return a single object (of some class other than the attribute category)
   * that indicates bounds on the legal values -- used, for example, by an
   * integer-valued attribute that must lie within a certain range.
   * </UL>
   * <P>
   *
   * @param category Printing attribute category to test. It must be a {@link java.lang.Class Class}
   * that implements interface {@link javax.print.attribute.Attribute Attribute}.
   * @param flavor Doc flavor for a supposed job, or null.
   * @param attributes Set of printing attributes for a supposed job (both job-level attributes and
   * document-level attributes), or null.
   * @return Object indicating supported values for <CODE>category</CODE>, or null if this Print
   * Service does not support specifying a doc-level or job-level attribute in <CODE>category</CODE>
   * in a Print Request.
   * @throws NullPointerException (unchecked exception) Thrown if <CODE>category</CODE> is null.
   * @throws IllegalArgumentException (unchecked exception) Thrown if <CODE>category</CODE> is not a
   * {@link java.lang.Class Class} that implements interface {@link javax.print.attribute.Attribute
   * Attribute}, or <code>DocFlavor</code> is not supported by this service.
   */
  public Object
  getSupportedAttributeValues(Class<? extends Attribute> category,
      DocFlavor flavor,
      AttributeSet attributes);

  /**
   * Determines whether a client can specify the given printing
   * attribute
   * value when setting up a job for this Print Service. A printing
   * attribute value is an instance of a class that implements interface
   * {@link javax.print.attribute.Attribute Attribute}.
   * <P>
   * If <CODE>flavor</CODE> is null and <CODE>attributes</CODE> is null or
   * is an empty set, this method tells whether this Print Service supports
   * the given printing attribute value for some possible combination of doc
   * flavor and set of attributes. If <CODE>flavor</CODE> is not null or
   * <CODE>attributes</CODE> is not an empty set, this method tells whether
   * this Print Service supports the given printing attribute value in
   * combination with the given doc flavor and/or set of attributes.
   * <p>
   * Also if DocFlavor is not null it must be a flavor supported by this
   * PrintService, else IllegalArgumentException will be thrown.
   * <p>
   * <code>DocAttribute</code>s which are to be specified on the
   * <code>Doc</code> must be included in this set to accurately
   * represent the context.
   * <p>
   * This is a convenience method to determine if the value
   * would be a member of the result of
   * <code>getSupportedAttributeValues(...)</code>.
   *
   * @param attrval Printing attribute value to test.
   * @param flavor Doc flavor for a supposed job, or null.
   * @param attributes Set of printing attributes for a supposed job (both job-level attributes and
   * document-level attributes), or null.
   * @return True if this Print Service supports specifying <CODE>attrval</CODE> as a doc-level or
   * job-level attribute in a Print Request, false if it doesn't.
   * @throws NullPointerException (unchecked exception)  if <CODE>attrval</CODE> is null.
   * @throws IllegalArgumentException if flavor is not supported by this PrintService.
   */
  public boolean isAttributeValueSupported(Attribute attrval,
      DocFlavor flavor,
      AttributeSet attributes);


  /**
   * Identifies the attributes that are unsupported for a print request
   * in the context of a particular DocFlavor.
   * This method is useful for validating a potential print job and
   * identifying the specific attributes which cannot be supported.
   * It is important to supply only a supported DocFlavor or an
   * IllegalArgumentException will be thrown. If the
   * return value from this method is null, all attributes are supported.
   * <p>
   * <code>DocAttribute</code>s which are to be specified on the
   * <code>Doc</code> must be included in this set to accurately
   * represent the context.
   * <p>
   * If the return value is non-null, all attributes in the returned
   * set are unsupported with this DocFlavor. The returned set does not
   * distinguish attribute categories that are unsupported from
   * unsupported attribute values.
   * <p>
   * A supported print request can then be created by removing
   * all unsupported attributes from the original attribute set,
   * except in the case that the DocFlavor is unsupported.
   * <p>
   * If any attributes are unsupported only because they are in conflict
   * with other attributes then it is at the discretion of the service
   * to select the attribute(s) to be identified as the cause of the
   * conflict.
   * <p>
   * Use <code>isDocFlavorSupported()</code> to verify that a DocFlavor
   * is supported before calling this method.
   *
   * @param flavor Doc flavor to test, or null
   * @param attributes Set of printing attributes for a supposed job (both job-level attributes and
   * document-level attributes), or null.
   * @return null if this Print Service supports the print request specification, else the
   * unsupported attributes.
   * @throws IllegalArgumentException if<CODE>flavor</CODE> is not supported by this PrintService.
   */
  public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
      AttributeSet attributes);

  /**
   * Returns a factory for UI components which allow users to interact
   * with the service in various roles.
   * Services which do not provide any UI should return null.
   * Print Services which do provide UI but want to be supported in
   * an environment with no UI support should ensure that the factory
   * is not initialised unless the application calls this method to
   * obtain the factory.
   * See <code>ServiceUIFactory</code> for more information.
   *
   * @return null or a factory for UI components.
   */
  public ServiceUIFactory getServiceUIFactory();

  /**
   * Determines if two services are referring to the same underlying
   * service.  Objects encapsulating a print service may not exhibit
   * equality of reference even though they refer to the same underlying
   * service.
   * <p>
   * Clients should call this method to determine if two services are
   * referring to the same underlying service.
   * <p>
   * Services must implement this method and return true only if the
   * service objects being compared may be used interchangeably by the
   * client.
   * Services are free to return the same object reference to an underlying
   * service if that, but clients must not depend on equality of reference.
   *
   * @param obj the reference object with which to compare.
   * @return true if this service is the same as the obj argument, false otherwise.
   */
  public boolean equals(Object obj);

  /**
   * This method should be implemented consistently with
   * <code>equals(Object)</code>.
   *
   * @return hash code of this object.
   */
  public int hashCode();

}
